/*
 * AGENT SHERPA
 *  
 * Assignement 2 of the Agent Oriented Software Engineering Course
 * M.Sc. in Advanced Software Engineering (Part-time)
 * University College Dublin www.ucd.ie
 *
 * Copyright (c) 2007 Chris Walsh, Aidan Morrisy and Iain Hull.
 * All rights reserved.
 * 
 * Filename: Main.aps
 * Author:   iain
 * Date:     08 February 2008
 */

package org.agentsherpa.model;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.imageio.ImageIO;

/**
 * The GlobalMap stores the grid coordinates of the road for the Agent 
 * playing area.  It loads this from a black and white mask image of the
 * road. 
 * 
 * @author iain
 *
 */
public class GlobalMap {
    private final int BLACK = 0xFF000000;
    private final int height;
    private final int width;
    private final Set<Point> road;
    
    /**
     * Contruct a new map from the specified image url
     * @param imageUrl
     * @throws MapLoadException if the url cannot be loaded
     */
    public GlobalMap(URL imageUrl) throws MapLoadException {
        BufferedImage img;
        try {
            Set<Point> temp = new HashSet<Point>(); 
            img = ImageIO.read(imageUrl);

            width = img.getWidth();
            height = img.getHeight();

            for (int i = 0; i < width; ++i) {
                for (int j = 0; j < height; ++j) {
                    if (BLACK == img.getRGB(i, j)) {
                        temp.add(new Point(i, j));
                    }
                    System.out.print(BLACK == img.getRGB(i, j) ? "*" : " ");
                }
                System.out.println();
            }
            
            road = Collections.unmodifiableSet(temp);
        }
        catch (IOException e) {
            e.printStackTrace();
            throw new MapLoadException("Unable to load global map", e);
        }
    }
    
    /**
     * The height of the map.
     * @return
     */
    public int getHeight() {
        return height;
    }

    /**
     * The width of the map.
     * @return
     */
    public int getWidth() {
        return width;
    }
    
    /**
     * Is the Point p part of the road.
     * @param p
     * @return
     */
    public boolean isRoad(Point p) {
        return road.contains(p);
    }
    
    /**
     * Find the next point in the map where there is road.  This is used to 
     * initially place agents.
     * @param p
     * @return
     */
    public Point findNextRoad(Point point) {
        System.out.print("findNextRoad: ");
        WritablePoint wpoint = new WritablePoint(point); 
        int x = point.getX();
        int y = point.getY();
        for (; x < width; ++x) {
            wpoint.setX(x);
            for(; y < height; ++y) {
                wpoint.setY(y);
                System.out.print(x + "," + y + " ");
                if (isRoad(wpoint)) {
                    System.out.println();
                    return new Point(x, y);
                }
            }
            y = 0;
        }
        System.out.println();
        return new Point(-1, -1);
    }

    public Set<Point> getRoadPoints() {
        return road;
    }
}
